<!DOCTYPE html>
<html lang="zh-cn">
  <head>
    
<meta charset="UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width,user-scalable=no,initial-scale=1,minimum-scale=1,maximum-scale=1">


<meta http-equiv="Cache-Control" content="no-transform" />
<meta http-equiv="Cache-Control" content="no-siteapp" />



  <meta name="description" content="依赖收集与派发更新"/>




  <meta name="keywords" content="Vue," />





  <link rel="alternate" href="/default" title="刘粉丝来了">






<link rel="canonical" href="http://yoursite.com/2020/04/21/watcher/"/>


<meta name="description" content="在Vue中数据变动视图就会对应的更新其中的流程你清楚吗？ 本章只说响应式 响应化另开一章  在Vue中的数据发生变化watch,computed就能追踪到并通知我们，这也是响应式的重点Object.defineProperty，此API里面包含get，set，开始阅读之前请记住get进行依赖收集，set进行派发更新，接下来这个观点将贯穿整篇。 开始前先看下这幅利流程图  接下来还是利用小demo">
<meta property="og:type" content="article">
<meta property="og:title" content="依赖收集与派发更新">
<meta property="og:url" content="http://yoursite.com/2020/04/21/watcher/index.html">
<meta property="og:site_name" content="刘粉丝来了">
<meta property="og:description" content="在Vue中数据变动视图就会对应的更新其中的流程你清楚吗？ 本章只说响应式 响应化另开一章  在Vue中的数据发生变化watch,computed就能追踪到并通知我们，这也是响应式的重点Object.defineProperty，此API里面包含get，set，开始阅读之前请记住get进行依赖收集，set进行派发更新，接下来这个观点将贯穿整篇。 开始前先看下这幅利流程图  接下来还是利用小demo">
<meta property="og:locale" content="zh_CN">
<meta property="og:image" content="http://120.79.197.3:8006/api/image/97939ac1b45e163676ef16f240e0f383.png">
<meta property="og:image" content="http://120.79.197.3:8006/api/image/f8656e53ddd5a2d8fcd0f71fa4937523.png">
<meta property="article:published_time" content="2020-04-21T15:29:18.000Z">
<meta property="article:modified_time" content="2020-04-21T18:10:32.215Z">
<meta property="article:author" content="刘粉丝来了">
<meta property="article:tag" content="Vue">
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="http://120.79.197.3:8006/api/image/97939ac1b45e163676ef16f240e0f383.png">


<link rel="stylesheet" type="text/css" href="/css/style.css?v=1.1" />
<link href='https://fonts.googleapis.com/css?family=Open+Sans' rel='stylesheet'>





<script type="text/javascript">
  var themeConfig = {
    fancybox: {
      enable: false
    },
  };
</script>




  



    <title> 依赖收集与派发更新 - 刘粉丝来了 </title>
  <meta name="generator" content="Hexo 4.2.0"></head>

  <body>
    <div id="page">
      <header id="masthead"><div class="site-header-inner">
    <h1 class="site-title">
        <a href="/." class="logo">刘粉丝来了</a>
    </h1>

    <nav id="nav-top">
        
            <ul id="menu-top" class="nav-top-items">
                
                    <li class="menu-item">
                        <a href="/">
                            
                            
                                Home
                            
                        </a>
                    </li>
                
                    <li class="menu-item">
                        <a href="/archives">
                            
                            
                                Archives
                            
                        </a>
                    </li>
                
                    <li class="menu-item">
                        <a href="/tags">
                            
                            
                                Tags
                            
                        </a>
                    </li>
                
                    <li class="menu-item">
                        <a href="/about">
                            
                            
                                About
                            
                        </a>
                    </li>
                
            </ul>
        
  </nav>
</div>

      </header>
      <div id="content">
        
    <div id="primary">
        
  <article class="post">
    <header class="post-header">
      <h1 class="post-title">
        
          依赖收集与派发更新
        
      </h1>

      <time class="post-time">
          4月 21 2020
      </time>
    </header>



    
            <div class="post-content">
            <blockquote>
<p>在Vue中数据变动视图就会对应的更新其中的流程你清楚吗？ 本章只说响应式 响应化另开一章</p>
</blockquote>
<p>在Vue中的数据发生变化<code>watch</code>,<code>computed</code>就能追踪到并通知我们，这也是响应式的重点<code>Object.defineProperty</code>，此API里面包含<code>get</code>，<code>set</code>，开始阅读之前请记住<code>get</code>进行依赖收集，<code>set</code>进行派发更新，接下来这个观点将贯穿整篇。</p>
<p>开始前先看下这幅利流程图<br><img src="http://120.79.197.3:8006/api/image/97939ac1b45e163676ef16f240e0f383.png" alt="响应式" title="响应式"></p>
<blockquote>
<p>接下来还是利用小demo加深印象 我们先做到把所有的数据进行代理，谁调用我或者谁修改我都要通知我一下</p>
</blockquote>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> Dog = observer(&#123;</span><br><span class="line">    name: <span class="string">'刘栓蛋'</span>,</span><br><span class="line">    IQ: <span class="number">-150</span></span><br><span class="line">&#125;)</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">observer</span>(<span class="params"> obj </span>) </span>&#123;</span><br><span class="line">    <span class="keyword">let</span> keys = <span class="built_in">Object</span>.keys( obj );</span><br><span class="line">    <span class="keyword">for</span>( <span class="keyword">let</span> i = <span class="number">0</span>; i &lt; keys.length; i++ ) &#123;</span><br><span class="line">        <span class="keyword">let</span> key = keys[i];</span><br><span class="line">        defineReactive( obj, key, obj[key], <span class="literal">true</span> );</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> obj;</span><br><span class="line">&#125;</span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">defineReactive</span>(<span class="params"> obj, key, value, enumerable </span>) </span>&#123;</span><br><span class="line">    <span class="built_in">Object</span>.defineProperty(obj,key,&#123;</span><br><span class="line">        configurable:<span class="literal">true</span>,</span><br><span class="line">        enumerable:!!enumerable,</span><br><span class="line">        <span class="keyword">get</span>() &#123;</span><br><span class="line">            <span class="built_in">console</span>.log( <span class="string">`<span class="subst">$&#123;key&#125;</span>我给调用了啦`</span> )</span><br><span class="line">            <span class="keyword">return</span> value;</span><br><span class="line">        &#125;,</span><br><span class="line">        <span class="keyword">set</span>( newVal ) &#123;</span><br><span class="line">            <span class="built_in">console</span>.log( <span class="string">`<span class="subst">$&#123;key&#125;</span>写入新数据啦`</span> )</span><br><span class="line">            value = newVal;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">Dog.name = <span class="string">'我栓蛋是个精神小伙'</span></span><br><span class="line"><span class="built_in">console</span>.log(Dog.name )</span><br><span class="line"></span><br><span class="line"><span class="comment">/** 会log出以下数据</span></span><br><span class="line"><span class="comment">    name写入新数据啦</span></span><br><span class="line"><span class="comment">    name我给调用了啦</span></span><br><span class="line"><span class="comment">    我栓蛋是个精神小伙</span></span><br><span class="line"><span class="comment">*/</span></span><br></pre></td></tr></table></figure>
<h3 id="开始分析："><a href="#开始分析：" class="headerlink" title="开始分析："></a><strong>开始分析：</strong></h3><ul>
<li>observer 的主要功能是分离出键和值传递给 defineReactive 进行代理</li>
<li>在访问属性时会先给代理拦截进而通知我，我目前的状态是什么</li>
</ul>
<p>上面的代码块只是告诉了我谁变了，但是视图没变动呀，给这代码加点料吧！！</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> Dog = observer(&#123;</span><br><span class="line">    name: <span class="string">'刘栓蛋'</span>,</span><br><span class="line">    IQ: <span class="number">-150</span></span><br><span class="line">&#125;)</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">observer</span>(<span class="params"> obj </span>) </span>&#123;</span><br><span class="line">    <span class="keyword">let</span> keys = <span class="built_in">Object</span>.keys( obj );</span><br><span class="line">    <span class="keyword">for</span>( <span class="keyword">let</span> i = <span class="number">0</span>; i &lt; keys.length; i++ ) &#123;</span><br><span class="line">        <span class="keyword">let</span> key = keys[i];</span><br><span class="line">        defineReactive( obj, key, obj[key], <span class="literal">true</span> );</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> obj;</span><br><span class="line">&#125;</span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">defineReactive</span>(<span class="params"> obj, key, value, enumerable </span>) </span>&#123;</span><br><span class="line">    <span class="keyword">let</span> deps = [];</span><br><span class="line">    <span class="built_in">Object</span>.defineProperty(obj,key,&#123;</span><br><span class="line">        configurable:<span class="literal">true</span>,</span><br><span class="line">        enumerable:!!enumerable,</span><br><span class="line">        <span class="keyword">get</span>() &#123;</span><br><span class="line">            <span class="built_in">console</span>.log( <span class="string">`<span class="subst">$&#123;key&#125;</span>我给调用了啦`</span> )</span><br><span class="line">            <span class="comment">// 此处是依赖收集</span></span><br><span class="line">            <span class="keyword">if</span> ( Dep.target &amp;&amp; deps.indexOf(Dep.target) &lt; <span class="number">0</span> ) &#123;</span><br><span class="line">                deps.push( Dep.target )</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="keyword">return</span> value;</span><br><span class="line">        &#125;,</span><br><span class="line">        <span class="keyword">set</span>( newVal ) &#123;</span><br><span class="line">            <span class="built_in">console</span>.log( <span class="string">`<span class="subst">$&#123;key&#125;</span>写入新数据啦`</span> )</span><br><span class="line">            value = newVal;</span><br><span class="line">            <span class="comment">// 此处为派发更新</span></span><br><span class="line">            deps.forEach( <span class="function"><span class="params">v</span> =&gt;</span> v() )</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 我是全局的 用来第三方中转的</span></span><br><span class="line">    <span class="keyword">let</span> Dep = &#123;</span><br><span class="line">        target:<span class="literal">null</span></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">function</span> <span class="title">notice</span>(<span class="params"> value </span>) </span>&#123;</span><br><span class="line">        <span class="built_in">console</span>.log( <span class="string">`我难道是个<span class="subst">$&#123;value&#125;</span>`</span> )</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">function</span> <span class="title">watcher</span>(<span class="params"> obj, key, callback </span>) </span>&#123;</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 派发更新时触发此函数</span></span><br><span class="line">        <span class="keyword">let</span> save = <span class="function"><span class="params">()</span> =&gt;</span> &#123;</span><br><span class="line">            <span class="keyword">let</span> value = callback();</span><br><span class="line">            notice( value );</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="built_in">Object</span>.defineProperty( obj, key, &#123;</span><br><span class="line">            configurable:<span class="literal">true</span>,</span><br><span class="line">            enumerable:<span class="literal">true</span>,</span><br><span class="line">            <span class="keyword">get</span>() &#123;</span><br><span class="line">                Dep.target = save;              </span><br><span class="line">                <span class="keyword">let</span> value = callback();</span><br><span class="line">                Dep.target = <span class="literal">null</span>;</span><br><span class="line">                <span class="keyword">return</span> value;</span><br><span class="line">            &#125;,</span><br><span class="line">            <span class="keyword">set</span>() &#123;</span><br><span class="line">                <span class="built_in">console</span>.log(<span class="string">'暂不做处理'</span>)</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;)</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    watcher( Dog,<span class="string">'status'</span>, () =&gt; &#123;</span><br><span class="line">        <span class="keyword">return</span> Dog.IQ &gt; <span class="number">1</span> ? <span class="string">'弟弟'</span> : <span class="string">'精神小伙'</span></span><br><span class="line">    &#125;)</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">`我是个怎样的人:<span class="subst">$&#123;Dog.status&#125;</span>`</span>)</span><br><span class="line">    Dog.IQ  = <span class="number">22</span></span><br></pre></td></tr></table></figure>
<h3 id="开始分析：-1"><a href="#开始分析：-1" class="headerlink" title="开始分析："></a><strong>开始分析：</strong></h3><ul>
<li>Dep作为第三方用来中转，在vue中一个Dep中有多个watcher，这里的watcher指的是被引用的属性，但在此示例中只写了一个固定的watcher就是Dep.IQ。</li>
<li>weatcher 这个函数传入三个参数， 分别是：主体属性，属性名，回调函数, 为什么需要写一个save函数呢？ 因为在派发更新的时候需要触发此函数，当触发 save 时又会触发 defineReactive 的get代理，等会我会用一画流程图说明。</li>
<li>当我们依赖收集的环节走完之后会把第三方的Dep.target清空。 </li>
</ul>
<p><img src="http://120.79.197.3:8006/api/image/f8656e53ddd5a2d8fcd0f71fa4937523.png" alt="响应式" title="依赖收集与派发更新"></p>
<p><strong>总结：</strong></p>
<ul>
<li>回到Vue中对比上面的demo，在Vue中组件里的属性只要给引用了就会生成一个watcher，当然我们会引用很多属性例如:name,ager,sex这样就会生成三个watcher,他们都会给压入当前组件的Dep中，这就是依赖收集。</li>
<li>在当前组件中我如果修改了 name ，就会马上进入代理的set方法，进行遍历Dep，查找当前的Dep中有没有一个watcher叫 name 的，有的话就通知我进行修改，这就是派发更新。<blockquote>
<p>本文到此结束 以上仅个人观点不一定正确 参考即可，希望对您有所帮助！</p>
</blockquote>
</li>
</ul>

            </div>
          

    
      <footer class="post-footer">
		
		<div class="post-tags">
		  
			<a href="/tags/Vue/">Vue</a>
		  
		</div>
		

        
        
  <nav class="post-nav">
    
      <a class="prev" href="/2020/05/03/Interview/">
        <i class="iconfont icon-left"></i>
        <span class="prev-text nav-default">面试之道 -- JS底层</span>
        <span class="prev-text nav-mobile">上一篇</span>
      </a>
    
    
      <a class="next" href="/2020/04/10/inversion/">
        <span class="next-text nav-default">virtual DOM如何与数据结合？ 如何将virtual DOM反转回DOM？</span>
        <span class="prev-text nav-mobile">下一篇</span>
        <i class="iconfont icon-right"></i>
      </a>
    
  </nav>

        
  <div class="comments" id="comments">
    
  </div>


      </footer>
    
  </article>


    </div>

      </div>

      <footer id="colophon"><script async src="https://dn-lbstatics.qbox.me/busuanzi/2.3/busuanzi.pure.mini.js">
</script>
<span class="copyright-year" style="width:100%; display:flex; justify-content: space-between;">
    <span>
        
        &copy;
    
        2014 -
    
    2020
    <span class="footer-author">刘粉丝来了.</span>
    <span class="power-by">
        由 <a class="hexo-link" href="https://hexo.io/" target="_blank" rel="noopener">Hexo</a> and <a class="theme-link" href="https://github.com/frostfan/hexo-theme-polarbear" target="_blank" rel="noopener">Polar Bear</a> 强力驱动
    </span>
    </span>
    <span id="busuanzi_container_site_pv">
        本站总访问量<span id="busuanzi_value_site_pv" style="color:red">24280</span>次
    </span>
</span>



      </footer>

      <div class="back-to-top" id="back-to-top">
        <i class="iconfont icon-up"></i>
      </div>
    </div>
    


    




  
    <script type="text/javascript" src="/lib/jquery/jquery-3.1.1.min.js"></script>
  

  

    <script type="text/javascript" src="/js/src/theme.js?v=1.1"></script>
<script type="text/javascript" src="/js/src/bootstrap.js?v=1.1"></script>


  </body>
</html>
